package com.borya.service.mobile.impl;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.time.Clock;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.borya.model.db.*;
import com.borya.model.enumcation.MerchantPowerLimit;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSONObject;
import com.borya.constant.RedisConstant;
import com.borya.dao.MerchantDAO;
import com.borya.dao.UserDAO;
import com.borya.framework.annotation.Autowired;
import com.borya.framework.annotation.Component;
import com.borya.framework.util.ObjectUtils;
import com.borya.model.entity.ApplyRecord;
import com.borya.model.entity.ChangeAddressInfo;
import com.borya.model.entity.FileInfo;
import com.borya.model.entity.Gps2Address;
import com.borya.model.entity.SupUserInfo;
import com.borya.service.impl.BaseServiceImpl;
import com.borya.service.mobile.MerchantService;
import com.borya.statuscode.StatusCode;
import com.borya.util.AliOSSUtil;
import com.borya.util.AliOSSUtil.UploadResult;
import com.borya.util.Constant;
import com.borya.util.Constant.SourceType;
import com.borya.util.DateUtils;
import com.borya.util.ImageUtils;
import com.borya.util.StringUtil;

@Component("merchantServiceImpl")
public class MerchantServiceImpl extends BaseServiceImpl implements MerchantService {

	private Logger log = Logger.getLogger(getClass());
	private Random random = new Random();

	@Autowired("userDAOImpl")
	private UserDAO userDAO;

	@Autowired("merchantDAO")
	private MerchantDAO merchantDAO;

	@Override
	public String getInfo(User user, JSONObject json) {
		final String dealerId = user.getDealerId();

		Merchant merchant = merchantDAO.getByDealerId(dealerId);
		if (Objects.isNull(merchant)) {
			log.error("DB connection exception.");
			return StatusCode.SYSTEM_EXCEPTION.toJSON();
		}
		int merAttr = merchant.getMerchant_attribute();
		String signOnlyPic = "";
		String applyPower = "";
		// 新增需求，在返回数据时取出签名一并返回，供隐私协议使用。
		// if (merAttr == 3 || merAttr == 4) {
		Map<String, String> powerInfo = merchantDAO.getPower(dealerId);
		if (powerInfo != null) {
			signOnlyPic = AliOSSUtil.generatePresignedUrl(AliOSSUtil.getDownloadUrl(powerInfo.get("img")));
			applyPower = powerInfo.get("apply_power");
		}
		if (StringUtils.isBlank(signOnlyPic) && StringUtils.isNotEmpty(merchant.getSignPicture())) {
			signOnlyPic = AliOSSUtil.generatePresignedUrl(AliOSSUtil.getDownloadUrl(merchant.getSignPicture()));
		}
		// }

		StringBuilder sb = new StringBuilder(512);
		sb.append("{");
		sb.append("\"dealerId\":\"" + dealerId + "\"");
		sb.append(",\"companyName\":\"" + merchant.getCompanyName() + "\"");
		sb.append(",\"address\":\"" + merchant.getAddress() + "\"");
		sb.append(",\"createTime\":\"" + merchant.getCreateTime() + "\"");
		sb.append(",\"signTime\":\"" + merchant.getSignTime() + "\"");
		sb.append(",\"status\":\"" + merchant.getStatus() + "\"");
		sb.append(",\"signMergePicture\":\""
				+ AliOSSUtil.generatePresignedUrl(AliOSSUtil.getDownloadUrl(merchant.getSignMergePicture())) + "\"");
		sb.append(",\"signOnlyPic\":\"" + signOnlyPic + "\"");
		// sb.append(",\"signOnlyPic\":\"https://192.168.10.109:6087/eas/unicom/20171218/171213666778/20171218161830_0002_18511527213_18.png\"");
		sb.append(",\"merchant_attribute\":\"" + merAttr + "\"");
		sb.append(",\"applyPower\":\"" + applyPower + "\"");
		sb.append(",\"devMac\":\"" + merchant.getDevMac() + "\"");
		sb.append(",\"phone\":\"" + user.getPhone() + "\"");
		sb.append("}");
		return StatusCode.SUCCESS.toDiyJson(true, "data", sb.toString());
	}

	@Override
	public String popChannelList(User user, JSONObject json) {
		final String dealerId = user.getDealerId();

		List<Merchant> list = merchantDAO.getLowerByDealerId(dealerId);
		if (Objects.isNull(list)) {
			log.error("DB connection exception.");
			return StatusCode.SYSTEM_EXCEPTION.toJSON();
		}

		StringBuilder sb = new StringBuilder(512);
		sb.append("{");
		sb.append("\"list\":[");
		int i = 0;
		for (Merchant merchant : list) {
			if (i++ != 0) {
				sb.append(",");
			}
			sb.append("{");
			sb.append("\"dealerId\":\"" + dealerId + "\"");
			sb.append(",\"companyName\":\"" + merchant.getCompanyName() + "\"");
			sb.append(",\"address\":\"" + merchant.getAddress() + "\"");
			sb.append(",\"createTime\":\"" + DateUtils.format(merchant.getCreateTime(), "yyyy-MM-dd HH:mm") + "\"");
			sb.append(",\"signTime\":\"" + DateUtils.format(merchant.getSignTime(), "yyyy-MM-dd HH:mm") + "\"");
			sb.append(",\"status\":\"" + merchant.getStatus() + "\"");
			sb.append(",\"phone\":\"" + merchant.getPhone() + "\"");
			switch (merchant.getStandardStatus()) {
			case Merchant.StandardStatus.STANDARD:
				sb.append(",\"standStatus\":\"" + merchant.getStandardStatus() + "\"");
				sb.append(",\"standTime\":\"" + DateUtils.format(merchant.getStandardTime(), "yyyy-MM-dd") + "\"");
				break;
			case Merchant.StandardStatus.NOT_STANDARD:
			default:
				sb.append(",\"standStatus\":\"" + merchant.getStandardStatus() + "\"");
				sb.append(",\"standTime\":\"未达标\"");
				break;
			}

			sb.append("}");
		}
		sb.append("]");
		sb.append("}");
		return StatusCode.SUCCESS.toDiyJson(true, "data", sb.toString());
	}

	@Override
	public String userInfo(User user, JSONObject json) {
		try {
			final String inviteCode = json.getString("inviteCode");
			if (StringUtils.isBlank(inviteCode)) {
				log.warn("param inviteCode error," + json);
				return StatusCode.PARAM_ERROR.toJSON("邀请码错误");
			}
			SupUserInfo sup = merchantDAO.getUserInfoByInviteCode(inviteCode);
			if (Objects.isNull(sup)) {
				log.warn("merchantDAO getUserInfoByInviteCode return null");
				return StatusCode.USER_NOT_FOUND.toJSON("上级商户不存在");
			}
			// 卡盟的用户不允许只允许输入卡盟的邀请码
			if (user.getSourceType() == SourceType.KAMENG && sup.getSourceType() != SourceType.KAMENG) {
				log.warn("非卡盟邀请码,userId=" + user.getUserId() + ",inviteCode=" + inviteCode);
				return StatusCode.PARAM_ERROR.toJSON("邀请码填写错误,请重新输入");
			}
			StringBuilder sb = new StringBuilder(256);
			sb.append("{\"dealerId\":\"").append(sup.getDealerId()).append("\"");
			sb.append(",\"companyName\":\"").append(sup.getCompanyName()).append("\"");
			sb.append(",\"userId\":\"").append(sup.getUserId()).append("\"");
			sb.append(",\"createTime\":\"").append(sup.getCreateTime()).append("\"");
			sb.append(",\"userName\":\"").append(sup.getUserName()).append("\"");
			sb.append("}");
			return StatusCode.SUCCESS.toDiyJson("data", sb);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return StatusCode.SYSTEM_EXCEPTION.toJSON();
		}
	}

	private static AtomicLong ato = new AtomicLong();

	private String getSysOrderId(String prifix, long nowTime) {
		final String tDateStr = DateUtils.format(nowTime, "yyMMddHHmmss");
		String s = String.valueOf(ato.getAndAdd(1));
		switch (s.length()) {
		case 1:
			return prifix + tDateStr + "0000" + s;
		case 2:
			return prifix + tDateStr + "000" + s;
		case 3:
			return prifix + tDateStr + "00" + s;
		case 4:
			return prifix + tDateStr + "0" + s;
		default:
			return prifix + tDateStr + s;
		}
	}

	/**
	 * 保存客户端上传上来的照片
	 *
	 * @param imgName
	 *            图片名称
	 * @param base64Str
	 *            图片base64编码字符串
	 * @param formatName
	 *            图片保存的格式，png，jpg
	 * @return true：保存成功，false：保存失败
	 * @throws IOException
	 */
	private String saveResigtImg(long nowTime, String imgName, String base64Str, String formatName) {
		final String date_str = DateUtils.format(nowTime, "yyyyMM");
		FileInfo fileInfo = FileInfo.newInstance(Constant.SpecialTag.ASKPOWER, date_str, imgName);
		byte[] bytes = Base64.getDecoder().decode(base64Str);
		ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
		UploadResult upload = AliOSSUtil.upload(byteArrayInputStream, fileInfo.getRelatePath());
		Boolean ok = upload.isFlag();
		log.debug("保存图片：" + imgName + (ok ? "成功" : "失败"));
		if (!ok)
			log.error("上传bass64文件至oss失败");
		return fileInfo.getRelatePath();
	}

	// @Override
	// public String getScopes(User user, JSONObject json) {
	// String type = json.getString("type");
	// final String dealerId = user.getDealerId();
	// List<String[]> agentState=merchantDAO.getAgentState(dealerId,type);
	// JSONArray list0 = new JSONArray();
	// Merchant mch = merchantDAO.getByDealerId(dealerId);
	// for(String[] item: agentState){
	// JSONObject agentObj = new JSONObject();
	// String type0=item[0];
	// String statue=item[1];
	// String name="未命名";
	// switch (type0) {
	// case "1":
	// name="远特通信";
	// //远特数据项and没有配置开通地域and商户属性为不为2 置为有远特权限
	// if(mch.getMerchant_attribute()!=2)
	// statue="2";
	// break;
	// case "2":
	// name="中国联通";
	// //联通数据项and没有配置开通地域and商户属性为不为A 置为有联通权限
	// if(mch.getMerchant_attribute()!=1)
	// statue="2";
	// break;
	// case "3":
	// name="中国移动"; break;
	// case "4":
	// name="中国电信"; break;
	// default:
	// break;
	// }
	// List<Scope> scopes=merchantDAO.getScopes(dealerId,type0);
	// agentObj.put("type", type0);
	// agentObj.put("state", statue);
	// agentObj.put("name", name);
	// agentObj.put("scopes", JSON.toJSON(scopes));
	// list0.add(agentObj);
	// }
	// JSONObject data = new JSONObject();
	// data.put("list", list0);
	// return StatusCode.SUCCESS.json().data(data).toString();
	// }

	@Override
	public String getScopesNew(User user, JSONObject json) {
		String type = json.getString("type");
		Merchant mch = merchantDAO.getByDealerId(user.getDealerId());
		if (Objects.isNull(mch)) {
			return StatusCode.USER_NOT_FOUND.json().toString();
		}
		List<Scope> allScops = merchantDAO.getAllScopes(type);
		if (Objects.isNull(allScops)) {
			log.info("getAllScopes return null," + type);
			return StatusCode.SYSTEM_EXCEPTION.json().toString();
		}
		List<String> merchantScops = merchantDAO.merchantScops(user.getDealerId());
		if (Objects.isNull(merchantScops)) {
			return StatusCode.SYSTEM_EXCEPTION.json().toString();
		}
		List<String> ingScops = merchantDAO.applyIngScop(user.getDealerId());
		if (Objects.isNull(ingScops)) {
			log.info("applyIngScop return null," + user.getDealerId());
			return StatusCode.SYSTEM_EXCEPTION.json().toString();
		}
		JSONObject ytJso = new JSONObject();
		ytJso.put("name", "远特通信");
		ytJso.put("type", "1");
		ytJso.put("state", "0");
		List<JSONObject> ytScops = new ArrayList<>();
		ytJso.put("scopes", ytScops);
		int ytState = 0;
		JSONObject ltJso = new JSONObject();
		ltJso.put("name", "联通通信");
		ltJso.put("type", "2");
		ltJso.put("state", "0");
		List<JSONObject> ltScops = new ArrayList<>();
		ltJso.put("scopes", ltScops);
		int ltState = 0;
		TbMerchantPowerLimit powerLimit = userDAO.searchPowerLimit(user.getDealerId(), MerchantPowerLimit.LIANTONG);
		boolean liantongLimit = ObjectUtils.nonNull(powerLimit);
		for (Scope scope : allScops) {
			JSONObject each = new JSONObject();
			each.put("area", scope.getArea());
			each.put("scopeId", scope.getScopeId());
			each.put("remark", scope.getRemark());
			each.put("type", scope.getType());
			each.put("specialType", scope.getSpecialType());
			int state = 0;
			if (merchantScops.contains(scope.getScopeId())) {
				state = 2;
			} else if (ingScops.contains(scope.getScopeId())) {
				state = 1;
			}
			each.put("state", state);
			switch (scope.getType()) {
			case 1:
				ytState = ytState < state ? state : ytState;
				ytScops.add(each);
				break;
			default:
				//如果限制联通 则过滤掉联通的选项
				ltState = ltState < state ? state : ltState;
				ltScops.add(each);
				break;
			}
		}
		ytJso.put("state", ytState + "");
		ltJso.put("state", ltState + "");
		List<JSONObject> list = new ArrayList<>();
		list.add(ytJso);
		if(!liantongLimit){
			list.add(ltJso);
		}
		JSONObject data = new JSONObject();
		data.put("list", list);
		return StatusCode.SUCCESS.json().data(data).toString();
	}



	@Override
	public String applyPower(User user, JSONObject json) {
		try {
			if (1 != user.getIsMain()) {
				log.warn("子账号无权限申请售卡权限");
				return StatusCode.NO_AUTHORITY.toJSON("子账号无权限申请售卡权限");
			}
			// scopeId判断是否和申请权限匹配，过滤申请联通权限+北京电信范围
			if (StringUtil.isNULL(json.getString("img")) || StringUtil.isNULL(json.getString("scopeId"))) {
				log.warn("param img error");
				return StatusCode.PARAM_ERROR.toJSON();
			}
			final String dealerId = user.getDealerId();
			final String img = json.getString("img");
			final String scopeId = json.getString("scopeId");

			Scope scope = merchantDAO.findScopeById(scopeId);
			String checkScope = checkScope(scope,scopeId,user);
			if(Objects.nonNull(checkScope)){
				return checkScope;
			}
			Merchant mch = merchantDAO.getByDealerId(dealerId);
			if (Objects.isNull(mch)) {
				log.warn("merchantDAO getApplyPowerInfo return null");
				return StatusCode.SYSTEM_EXCEPTION.toJSON();
			}
			if (0 != mch.getStatus()) {
				log.warn("未激活商户不允许申请权限," + mch.toString());
				return StatusCode.NO_AUTHORITY.toJSON("尊敬的用户您好，请在激活之后再申请售卡权限。");
			}
			final int attribute_status = mch.getAttribute_status();
			if (1 == attribute_status) {
				log.warn("商户权限升级审核中," + user);
				return StatusCode.CONDITION_DEL_ING.toJSON("商户业务权限正在审核中，请耐心等待审核结果");
			}

			ApplyPower app = new ApplyPower();
			app.setDealer_id(dealerId);
			app.setCompany_name(mch.getCompanyName());
			app.setMerchant_attribute(mch.getMerchant_attribute());
			app.setAttribute_status(mch.getAttribute_status());
			app.setStatus(1);// 插入售卡权限申请表即为待处理
			final int merchant_attribute = app.getMerchant_attribute();
			app.setBefore_power(merchant_attribute);
			switch (merchant_attribute) {
			case 1:
				app.setApply_power(3);
				break;
			case 2:
				app.setApply_power(4);
				break;
			default:
				// log.info("权限错误,"+merchant_attribute);
				// return StatusCode.CONDITION_DEL_ING.toJSON("您的开卡权限已开通");
			}
			long nowTime = Clock.systemDefaultZone().millis();
			String imgUrl = saveResigtImg(nowTime, dealerId + String.valueOf(nowTime) + ".png", img, "png");
			if (null == imgUrl)
				return StatusCode.SYSTEM_EXCEPTION.toJSON();
			app.setOrder_id(getSysOrderId("AP", nowTime));
			app.setCreate_time(nowTime);
			app.setImg(imgUrl);
			app.setUser_id(user.getUserId());
			app.setUser_name(user.getUserName());
			app.setUser_phone(user.getPhone());
			app.setScopeId(scopeId);// 申请售卡权限时范围待做
			app.setLatitude(user.getLatitude());
			app.setLongitude(user.getLongitude());
			Gps2Address gps2Address = new Gps2Address(user.getLatitude(), user.getLongitude());
			setAddress(gps2Address);
			app.setReqAddress(gps2Address.getAddress());
			boolean r = merchantDAO.addApplyPowerOrder(app);
			if (!r) {
				log.warn("权限申请入表失败");
				return StatusCode.SYSTEM_EXCEPTION.toJSON();
			}
			return StatusCode.SUCCESS.toJSON();
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return StatusCode.SYSTEM_EXCEPTION.toJSON();
		}

	}

	private String checkScope(Scope scope,String scopeId,User user){
		if (Objects.isNull(scope)) {
			log.warn("scopeId:" + scopeId + "错误");
			return StatusCode.PARAM_ERROR.toJSON("区域码未找到，请刷新后重试。");
		}
		TbMerchantPowerLimit powerLimit = userDAO.searchPowerLimit(user.getDealerId(), MerchantPowerLimit.LIANTONG);
		if(ObjectUtils.nonNull(powerLimit)){
			log.info("商户限制了联通权限，"+powerLimit);
			return StatusCode.NO_AUTHORITY.json().msg("功能建设中，敬请期待").toString();
		}
		if(ObjectUtils.nonNullOrEmpty(scope.getRefuseReason())){
			return StatusCode.NO_AUTHORITY.json().msg(scope.getRefuseReason()).toString();
		}
		if (scope.getType() != 1) {
			if (0 == user.getTokenInfo().getLocationFlag()) {
				log.info("位置信息未打开，locationflag:" + user.getTokenInfo().getLocationFlag());
				return StatusCode.ADDRESS_CLOSE.toJSON();
			}
			if (ObjectUtils.isNullOrEmpty(user.getLatitude()) || ObjectUtils.isEqual("0", user.getLatitude())
					|| ObjectUtils.isNullOrEmpty(user.getLongitude())
					|| ObjectUtils.isEqual("0", user.getLongitude())) {
				log.info("gps位置未获取到:" + user.toString());
				return StatusCode.ADDRESS_NOT_GET.toJSON();
			}
		}
		return null;
	}

	@Override
	public String applyScope(User user, JSONObject json) {
		if (StringUtil.isNULL(json.getString("type")) || StringUtil.isNULL(json.getString("scopeId"))) {
			log.warn("param img error");
			return StatusCode.PARAM_ERROR.toJSON();
		}
		String scopeId = json.getString("scopeId");
		Integer type = json.getInteger("type");
		final String dealerId = user.getDealerId();
		// 当前用户是否有权限
		if (1 != user.getIsMain()) {
			log.warn("子账号无权限申请售卡权限");
			return StatusCode.NO_AUTHORITY.toJSON("子账号无权限申请售卡范围");
		}
		Scope scope = merchantDAO.findScopeById(scopeId);
		String checkScope = checkScope(scope,scopeId,user);
		if(Objects.nonNull(checkScope)){
			return checkScope;
		}
		Merchant mch = merchantDAO.getByDealerId(dealerId);
		if (null == mch) {
			log.warn("merchantDAO getByDealerId return null");
			return StatusCode.SYSTEM_EXCEPTION.toJSON();
		}
		// 商户未激活
		if (0 != mch.getStatus()) {
			log.warn("未激活商户不允许申请权限," + mch.toString());
			return StatusCode.NO_AUTHORITY.toJSON("尊敬的用户您好，请在激活之后再申请售卡范围。");
		}
		// 不具备运营商售卡权限（只做联通）1
		final int merAttr = mch.getMerchant_attribute();
		if (type == 2 && merAttr == 1) {
			log.warn("无联通售卡权限商户不允许申请售卡范围," + mch.toString());
			return StatusCode.NO_AUTHORITY.toJSON("尊敬的用户您好，请在获得联通售卡权限之后再申请售卡范围。");
		}
		// 不具备运营商售卡权限（扩展到全部）2
		// 查询tb_merchant_config left join tb_sell_scope_pool 看当前dealer_id and
		// type是否有记录，有才可以没有就返回提示“用户没有开通营运商权限”
		// boolean isHaveType=merchantDAO.isScopeById(dealerId,"",type);
		// if(!isHaveType){
		// log.info("商户没有营运商权限,"+user);
		// return StatusCode.CONDITION_DEL_ING.toJSON("商户没有营运商权限，请申请先申请营运商权限");
		// }
		// 已经有了该售卡范围
		boolean isHave = merchantDAO.isScopeById(dealerId, scopeId, 0);
		if (isHave) {
			log.warn("商户申请售卡范围已存在," + user);
			return StatusCode.CONDITION_DEL_ING.toJSON("商户申请售卡范围已存在，请勿重复申请");
		}
		// 待申请地区已在申请队列中
		ApplyPower ap = merchantDAO.getApplyScope(dealerId, scopeId);
		if (ap != null && ap.getStatus() == 1) {
			log.warn("商户申请售卡范围正在处理中," + user);
			return StatusCode.CONDITION_DEL_ING.toJSON("商户申请售卡范围正在处理中，请勿重复申请");
		}
		// 组装数据，插入审核数据表
		ApplyPower newAp = new ApplyPower();
		newAp.setDealer_id(dealerId);
		newAp.setCompany_name(mch.getCompanyName());
		newAp.setMerchant_attribute(merAttr);
		newAp.setAttribute_status(mch.getAttribute_status());
		newAp.setStatus(1);// 入库即为待审核
		newAp.setBefore_power(merAttr);
		newAp.setApply_power(merAttr);// 申请范围 售卡权限为原权限
		final long nowTime = System.currentTimeMillis();
		newAp.setOrder_id(getSysOrderId("AP", nowTime));
		newAp.setCreate_time(nowTime);
		newAp.setImg("");// 没有签名，置为空
		newAp.setUser_id(user.getUserId());
		newAp.setUser_name(user.getUserName());
		newAp.setUser_phone(user.getPhone());
		newAp.setScopeId(scopeId);
		newAp.setLatitude(user.getLatitude());
		newAp.setLongitude(user.getLongitude());
		Gps2Address gps2Address = new Gps2Address(user.getLatitude(), user.getLongitude());
		setAddress(gps2Address);
		newAp.setReqAddress(gps2Address.getAddress());
		boolean r = merchantDAO.addApplyPowerOrder(newAp);
		if (!r) {
			log.warn("售卡范围申请入表失败");
			return StatusCode.SYSTEM_EXCEPTION.toJSON();
		}
		return StatusCode.SUCCESS.toJSON();
	}

	@Override
	public List<ApplyRecord> getApplyRecords(String dealerId, Integer pageSize, Integer pageIndex) {
		return merchantDAO.getApplyRecords(dealerId, pageSize, pageIndex);
	}

	@Override
	public String setImg(User member, JSONObject json, int type) {
		switch (type) {
		case 1:
			return shpqSign(member.getDealerId(), json.getString("img").trim());
		default:
			return StatusCode.SYSTEM_EXCEPTION.json().toString();
		}
	}

	private String shpqSign(String dealerId, String base64Str) {
		try {
			String date2 = DateUtils.format(Clock.systemDefaultZone().millis(), "yyyyMMdd");
			String imgName = "sign" + date2 + dealerId + ".jpg";
			FileInfo fileInfo = FileInfo.newInstance(Constant.SpecialTag.SHQP, dealerId, imgName);
			boolean ok = ImageUtils.writeImg(fileInfo.getParentPath(), fileInfo.getFileName(), base64Str);
			if (!ok) {
				log.error("图片保存到服务器失败");
				return StatusCode.SYSTEM_EXCEPTION.toJSON("图片保存到服务器失败");
			}
			UploadResult upload = AliOSSUtil.upload(fileInfo.getFilePath(), fileInfo.getRelatePath());
			if (!upload.isFlag()) {
				log.error("图片保存到oss失败");
				return StatusCode.SYSTEM_EXCEPTION.toJSON("图片保存到oss失败");
			}
			JSONObject data = new JSONObject();
			data.put("imgName", imgName);
			return StatusCode.SUCCESS.toDiyJson("data", data);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return StatusCode.SYSTEM_EXCEPTION.json().toString();
		}
	}

	@Override
	public String shqpRenew(User user, JSONObject json) {
		try {
			final String signImg = json.getString("signImg");
			if (ObjectUtils.isNullOrEmpty(signImg)) {
				log.warn("param signImg is empty");
				return StatusCode.PARAM_ERROR.json().msg("签名照不存在。").toString();
			}
			if (user.getIsMain() != 1) {
				log.warn("子账号无权限续约授权牌");
				return StatusCode.NO_AUTHORITY.toJSON("子账号无权限续约授权牌");
			}
			FileInfo signFileInfo = FileInfo.newInstance(Constant.SpecialTag.SHQP, user.getDealerId(), signImg);
			String signPath = signFileInfo.getFilePath();
			boolean isExist = AliOSSUtil.doseObjectExist(signFileInfo.getRelatePath().substring(1));
			if (!isExist) {
				log.warn("签名照未找到，" + signPath);
				return StatusCode.PARAM_ERROR.json().msg("签名照未找到。").toString();
			}
			File signFile = new File(signPath);
			if (signFile.exists()) {
				signFile.delete();
			}
			ShqpInfo shqpInfo = merchantDAO.getShqpInfo(user.getDealerId());
			if (ObjectUtils.isNullOrEmpty(shqpInfo.getShpqId())) {
				log.warn("授权牌信息有误，无授权编号，" + user.getDealerId());
				return StatusCode.SYSTEM_EXCEPTION.json().msg("授权编号未找到。").toString();
			}
			String endDate = DateUtils.getExpectDate(1, 0, -1, "yyyyMMdd");
			String ossSignUrl = AliOSSUtil.getDownloadUrl(signFileInfo.getRelatePath());
			shqpInfo.setSignUrl(ossSignUrl);
			shqpInfo.setShqpEndTime(Integer.parseInt(endDate));
			shqpInfo.setModifyTime(Clock.systemDefaultZone().millis());
			String year = endDate.substring(0, 4);
			String month = endDate.substring(4, 6);
			String day = endDate.substring(6, 8);
			boolean makeShqpImg = makeShqpImg(shqpInfo, year, month, day, 2, user.getSourceType());

			if (!makeShqpImg) {
				log.warn("修改授权牌信息失败," + shqpInfo.toString());
				return StatusCode.SYSTEM_EXCEPTION.json().toString();
			}
			String content;
			if (user.getSourceType() == 1) {
				content = String.format(
						"尊敬的%s商户，您申请的%s远特商户授权牌续约已成功，有效期至%s年%s月%s日，" + "可在“授权牌管理”页面内生成全新电子授权牌并保存。感谢您对%s的支持！", "卡盟", "卡盟",
						year, month, day, "卡盟");
			} else {
				content = String.format("尊敬的商户，您申请的远特商户授权牌续约已成功，有效期至%s年%s月%s日。" + "感谢您的支持！", year, month, day);
			}

			sendMsgNormal(user.getUserId(), "授权牌续约通知", content, "245");
			JSONObject data = new JSONObject();
			data.put("url", AliOSSUtil.generatePresignedUrl(shqpInfo.getShqpUrl()));
			return StatusCode.SUCCESS.json().data(data).toString();
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return StatusCode.SYSTEM_EXCEPTION.json().toString();
		}
	}

	@Override
	public String applyChangeAddress(User user, JSONObject json) {
		final String newAddress = json.getString("newAddress");
		final String newCompleteAddress = json.getString("newCompleteAddress");
		if (StringUtil.isNULL(newAddress) || StringUtil.isNULL(newCompleteAddress)) {
			log.warn("参数错误：newAddress = " + newAddress + " newCompleteAddress = " + newCompleteAddress);
			return StatusCode.PARAM_ERROR.json().msg("请填写新地址。").toString();
		}
		ChangeAddressInfo oldAInfo = merchantDAO.getMerchantByUserId(user.getUserId());
		if (StringUtil.isNULL(oldAInfo)) {
			log.warn("applyChangeAddress --> 用户相关信息未找到 userId = " + user.getUserId());
			return StatusCode.NO_CONTENT.json().msg("用户相关信息未找到。").toString();
		}
		if (StringUtil.isNULL(oldAInfo.getOldAddress())) {
			log.warn("applyChangeAddress --> 商户旧门店地址未填写 userId = " + user.getUserId());
			return StatusCode.NO_CONTENT.json().msg("商户旧门店地址未填写，请补全后再进行更改。").toString();
		}
		boolean count = merchantDAO.countChangeAddress(oldAInfo.getMerchantId());
		if (count) {
			log.warn("applyChangeAddress --> 已有申请记录");
			return StatusCode.FORBID_MODIFY.json().msg("已申请修改地址，请等待管理员审核。").toString();
		}
		try {
			ChangeAddressInfo lastTime = merchantDAO.getChangeAddressLast(user.getUserId());
			Long time = System.currentTimeMillis();
			ChangeAddressInfo info = new ChangeAddressInfo();
			info.setCreateTime(time);
			info.setUpdateTime(time);
			String orderId = "M" + user.getUserId() + time.toString().substring(9, time.toString().length());
			info.setOrderId(orderId);// 订单id
			info.setUserId(user.getUserId());// 账户id
			info.setUserPhone(oldAInfo.getUserPhone());// 用户手机号
			info.setUserName(oldAInfo.getUserName());// 用户姓名
			info.setUserAdmin(oldAInfo.getUserAdmin());// 用户主工号
			info.setMerchantId(oldAInfo.getMerchantId());// 商户id
			int sourceType = 1;
			if (oldAInfo.getSourceType().intValue() != 1) {
				sourceType = 2;
			}
			info.setOrderSource(sourceType);// 订单来源 1卡盟2新零售
			String oldAddress = StringUtil.isNULL(oldAInfo.getOldAddress()) ? "" : oldAInfo.getOldAddress();
			info.setOldAddress(oldAddress);// 旧地址
			info.setNewAddress(newAddress);// 新地址
			info.setIsAdopt(0);// 是否通过审核0：没有 1通过 2拒绝
			info.setNewCompleteAddress(newCompleteAddress);// 完整新地址
			info.setOldCompleteAddress(oldAInfo.getOldCompleteAddress().replace(oldAddress, ""));// 完整旧地址
			if (!StringUtil.isNULL(lastTime)) {
				log.warn("applyChangeAddress -lastTime -> " + lastTime);
				info.setLastTime(lastTime.getCreateTime());
			}
			boolean insert = merchantDAO.insertChangeAddress(info);
			if (insert) {
				return StatusCode.SUCCESS.json().toString();
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return StatusCode.SYSTEM_EXCEPTION.json().toString();
		}
		return StatusCode.SYSTEM_EXCEPTION.json().toString();
	}

	@Override
	public String getAddress(User user) {
		JSONObject data = new JSONObject();
		ChangeAddressInfo oldAInfo = merchantDAO.getMerchantByUserId(user.getUserId());
		if (StringUtil.isNULL(oldAInfo)) {
			log.warn("applyChangeAddress --> 用户相关信息未找到 userId = " + user.getUserId());
			return StatusCode.NO_CONTENT.json().msg("用户相关信息未找到。").toString();
		}
		if (oldAInfo.getIsMain() != 1) {
			log.warn("applyChangeAddress --> 不是主工号 userId = " + user.getUserId());
			return StatusCode.NO_REGIST_ERR.json().msg("子工号不允许变更门店地址。").toString();
		}
		if (oldAInfo.getRegistTime() == 0) {
			log.warn("applyChangeAddress --> 用户没有激活商户 userId = " + user.getUserId());
			return StatusCode.NO_REGIST_ERR.json().msg("您还没有激活，请前往绑定激活设备。").toString();
		}
		if (oldAInfo.getFillStatus() == 1 || oldAInfo.getFillStatus() == 3 || oldAInfo.getFillStatus() == 4) {
			log.warn("applyChangeAddress --> 用户待补录 userId = " + user.getUserId());
			return StatusCode.NO_REGIST_ERR.json().msg("商户待补录中，不允许变更门店地址。").toString();
		}
		boolean count = merchantDAO.countChangeAddress(oldAInfo.getMerchantId());
		if (count) {
			log.warn("applyChangeAddress --> 已有申请记录");
			return StatusCode.FORBID_MODIFY.json().msg("已申请修改地址，请等待管理员审核。").toString();
		}
		String address = StringUtil.isNULL(oldAInfo.getOldAddress()) ? "" : oldAInfo.getOldAddress();
		String oldCompleteAddress = oldAInfo.getOldCompleteAddress();
		try {
			oldCompleteAddress = oldCompleteAddress.replace(address, "");
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		data.put("address", address);
		if (StringUtil.isNULL(address)) {
			data.put("addressDetail", "");
		} else {
			data.put("addressDetail", oldCompleteAddress);
		}
		return StatusCode.SUCCESS.toDiyJson("data", data);
	}

	protected String getApiAk() {
		final String aks = userDAO.redis_get(RedisConstant.BAIDU_API_AK);
		if (ObjectUtils.isNullOrEmpty(aks)) {
			return Constant.ApiConf.BAIDU_MAP_APK;
		}
		List<String> list = Stream.of(aks.split(",")).collect(Collectors.toList());
		return list.stream().skip(random.nextInt(list.size())).findAny().get();
	}

	@Override
	public String getSpreadAuthority(User user) {
		// [商户]激活设备后才可以分享
		String merchantId = user.getMerchantId();
		// 查询判断黑名单
		Boolean bool = userDAO.checkBlackUser(user.getUserId());
		if (Objects.isNull(bool)) {
			log.error("DB连接异常,查询商户信息userId=" + user.getUserId());
			return StatusCode.PARAM_ERROR.toJSON("网络异常,请稍后再试");
		}
		if (bool) {
			log.error("黑名单用户不允许分享,查询商户信息userId=" + user.getUserId());
			return StatusCode.PARAM_ERROR.toJSON("黑名单用户操作受限制,请联系管理员");
		}

		Merchant merchant = merchantDAO.getByMerchantId(merchantId);
		if (Objects.isNull(merchant)) {
			log.error("DB连接异常,查询商户信息merchatId=" + merchantId);
			return StatusCode.PARAM_ERROR.toJSON("网络异常,请稍后再试");
		}
		// 商户被注销
		if (merchant.getFlag() == -1) {
			log.error("商户被注销,查询商户信息merchantId=" + merchant.getMerchantId());
			return StatusCode.PARAM_ERROR.toJSON("商户被注销,操作受限制,请联系管理员");
		}

		if (Constant.EXTENSION_FLAG) {
			// 查询商户激活状态、激活时间
			if (merchant.getStatus() != 0 || merchant.getRegistTime() == 0L) {
				log.error("商户未激活不允许分享merchatId=" + merchantId);
				return StatusCode.PARAM_ERROR.toJSON("未激活不允许分享,请先激活设备");
			}

			int allowSpreadFlag = 0;
			// 已激活判断
			if (merchant.getStatus() == 0 && merchant.getRegistTime() > 0) {
				allowSpreadFlag = 1;
			}

			JSONObject json = new JSONObject();
			json.put("allowSpreadFlag", allowSpreadFlag);
			return StatusCode.SUCCESS.toDiyJson("data", json);
		}

		JSONObject json = new JSONObject();
		json.put("allowSpreadFlag", 1);
		return StatusCode.SUCCESS.toDiyJson("data", json);
	}

}